/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package memoria.intermedia;

/**
 *
 * @author MARI
 */
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author user
 */
public class MemoriaIntermedia {
    static final Logger logger = Logger.getLogger("Gestion de buffer");
    //Bloquese de la memoria intermedia
    private pagina[] buffer;
    //Numero total de paginas en el buffer
    private int numeroPaginas;
    //Posicion de la ultima pagina en el buffer
    private int posicionultimapagina=-1;
    //Cola para el control de Sustitucion basada en LRU
    private Queue colaLRU;
    
    public MemoriaIntermedia(int numeroPaginas)
    {
        this.numeroPaginas=numeroPaginas;
        //Crear el buffer con paginas vacias
        buffer=new pagina[numeroPaginas];
        //Crear una cola FIFO
        colaLRU=new LinkedList<Integer>();
    }
    
    
    public pagina recuperarPaginaDelBuffer(int numeroPagina)
    {
        //verificamos si la pagina esta en el buffer
        int posicion=posicionDePaginaEnBuffer(numeroPagina);
        if (posicion>=0)
        {
            //Marcar pagina o bloque como recientemente referenciado
            colaLRU.remove(numeroPagina);
            colaLRU.add(numeroPagina);
            //devolver la pagina del buffer
            return buffer[posicion];
        }
        return null;
    }
    public pagina ponerPaginaEnBuffer(pagina Pagina)
    {
        if (estaPaginaEnBuffer(Pagina)){
            //VERIFICAR EN TEORIA SI SE TIENE QUE ACTUALIZAR EL LRU
            return null;
        }
        else if (!bufferLleno()){
            posicionultimapagina++;
            buffer[posicionultimapagina]=Pagina;
            //actualizar el LRU
            colaLRU.remove(posicionultimapagina);
            colaLRU.add(posicionultimapagina);
            return null;
        }
        else{
            //recuperar la pagina a descartar
            int numeroPaginaDescartada=(Integer) colaLRU.remove();
            int posicion=posicionDePaginaEnBuffer(numeroPaginaDescartada);
            pagina PaginaDescartada=buffer[posicion];
            buffer[posicion]=Pagina;
            colaLRU.add(Pagina.getNumeroPagina());
            return PaginaDescartada;
        }
    }
    
    private int posicionDePaginaEnBuffer(int numeroPagina)    
    {
        int posicion=-1;
        for(int i=0;i<buffer.length;i++){
            if ((buffer[i] != null) && (numeroPagina==buffer[i].getNumeroPagina())){
                posicion=i;
                break;
            }
        }
        return posicion;
    }
    
    private boolean estaPaginaEnBuffer(pagina Pagina) {
        return(posicionDePaginaEnBuffer(Pagina.getNumeroPagina()) != -1);
    }
    
    private boolean bufferLleno() {
        return numeroPaginas -1 == posicionultimapagina;
    }
    
    @Override
    public String toString() {
        String resultado = "";
        for (int i=0; i< buffer.length; i++) {
            resultado += "Pagina[" + i + "]: " + buffer[i] + "\n";
        }
        return resultado + "\n" + this.colaLRU;
    }
    
    public static void main(String[] args){
        //crear un gestor de memoria
        MemoriaIntermedia gestorBuffer=new MemoriaIntermedia(6);
        //Paginas del disco
        System.out.println("Paginas del Disco: ");
        pagina[] paginas= new pagina[10];
        for (int i=0; i< paginas.length; i++) {
            pagina Pagina= new pagina(i,"p"+i);
            paginas[i] = Pagina;
            System.out.println(Pagina);
        }  
        System.out.println("Contenido del Gestor: ");
        System.out.println(gestorBuffer);
        for (int i=0; i< paginas.length; i++) {
            gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
        }
        System.out.println("Contenido del Gestor despues de poner bloques: ");
        System.out.println(gestorBuffer);
        System.out.println("Poner una pagina al buffer: ");
        pagina paginaN=new pagina(10,"p10");
        pagina paginaE = gestorBuffer.ponerPaginaEnBuffer(paginaN);
        System.out.println(paginaE);
        System.out.println(gestorBuffer);
        
        System.out.println("Recuperar una pagina del Buffer: ");
        pagina pagina1=gestorBuffer.recuperarPaginaDelBuffer(7);
        System.out.println(pagina1);
        System.out.println(gestorBuffer);
        
        System.out.println("Recuperar otra pagina del Buffer: ");
        pagina pagina2=gestorBuffer.recuperarPaginaDelBuffer(12);
        System.out.println(pagina2);
        System.out.println(gestorBuffer);
        
    }
    
}
